package com.binance.gateway.filter.gray;


import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import com.binance.gateway.app.base.dto.SessionDto;
import com.binance.gateway.app.base.helper.BaseHelper;
import com.binance.gateway.constant.GwFilterOrders;
import com.binance.master.constant.Constant;
import com.binance.master.ribbon.support.RibbonFilterContextHolder;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

import lombok.extern.slf4j.Slf4j;


@Component
@Slf4j
public class GrayFilter extends ZuulFilter {
    @Value("${grayRule}")
    private String grayRule;

    @Override
    public int filterOrder() {
        return GwFilterOrders.AUTH + 1;
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        // a filter has already forwarded
        // a filter has already determined serviceId
        return !ctx.containsKey(FilterConstants.FORWARD_TO_KEY) && !ctx.containsKey(FilterConstants.SERVICE_ID_KEY);
    }

    @Override
    public Object run() {
        // 分流算法实现，符合该规则，则流量优先打到标记为gray的服务器上，找不到则随机找可用服务器
        // 暂时支持简单算法：cookie|cookie 或 mod|xx 或userId|xxxx
        RequestContext ctx = RequestContext.getCurrentContext();
        boolean gotoGray = false;
        String defalutGrayEnvFlag = Constant.ENV_FLAG_GRAY;
        if (StringUtils.isNotBlank(grayRule)) {
            String[] rules = grayRule.split("\\|");
            if (rules.length > 1) {
                if (StringUtils.equals("cookie", rules[0])) {
                    String envFlagCookie = BaseHelper.getCookieValue(ctx.getRequest(), rules[1]);
                    if (StringUtils.isNotEmpty(envFlagCookie)) {
                        // 默认环境设置为cookie中写入的值，这样方便个人连dev调试
                        defalutGrayEnvFlag = envFlagCookie;
                        gotoGray = true;
                    }
                } else {
                    SessionDto sessionDto =
                            (SessionDto) ctx.get(com.binance.gateway.app.constant.Constant.SESSION_INFO_KEY);
                    if (StringUtils.equals("userId", rules[0]) && rules[1] != null) {
                        if (sessionDto != null && StringUtils.indexOf(rules[1], sessionDto.getUserId()) > 0) {
                            gotoGray = true;
                        }
                    } else if (StringUtils.equals("mod", rules[0])) {
                        if (sessionDto != null && NumberUtils.toInt(StringUtils.right(sessionDto.getUserId(), 2))
                                % 100 == NumberUtils.toInt(rules[1], 1)) {
                            gotoGray = true;
                        }
                    }
                }
            }
        }
        if (gotoGray) {
            // 设置灰度环境标识
            ctx.addZuulRequestHeader(Constant.GRAY_ENV_HEADER, defalutGrayEnvFlag);
            RibbonFilterContextHolder.getCurrentContext().setEnvFlag(defalutGrayEnvFlag);
            log.info("go to gray env: {}", defalutGrayEnvFlag);
        } else {
            // 正常环境标识
            ctx.addZuulRequestHeader(Constant.GRAY_ENV_HEADER, Constant.ENV_FLAG_NORMAL);
            RibbonFilterContextHolder.getCurrentContext().setEnvFlag(Constant.ENV_FLAG_NORMAL);
        }
        return null;
    }
}
